package org.ru.mse10.cvfpg.generator;

import java.io.File;

import org.ru.mse10.cvfpg.generator.constants.FoAttributes;
import org.ru.mse10.cvfpg.generator.constants.FoTags;
import org.ru.mse10.cvfpg.generator.constants.Namespace;
import org.ru.mse10.cvfpg.generator.constants.XsltAttributes;
import org.ru.mse10.cvfpg.generator.constants.XsltTags;
import org.ru.mse10.cvfpg.model.Block;
import org.ru.mse10.cvfpg.model.Format;
import org.ru.mse10.cvfpg.model.Page;
import org.ru.mse10.cvfpg.model.PageFlow;
import org.ru.mse10.cvfpg.model.Text;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Generator {

	public static File generate(Format format) throws Exception {
		Document xsltDocument = DocumentUtil.createXsltDocument();
		Element root = (Element) xsltDocument.getFirstChild();
		Element rootTemplate = DocumentUtil.appendElement(xsltDocument, root, XsltTags.TEMPLATE, Namespace.XSLT);
		DocumentUtil.setAttribute(rootTemplate, XsltAttributes.ATTR_MATCH, "/");

		Element foRoot = DocumentUtil.appendElementNS(xsltDocument, rootTemplate, FoTags.ROOT, Namespace.FO);
		for (Page page : format.getPages()) {
			Element simplePageMaster = DocumentUtil.appendElement(xsltDocument, foRoot, FoTags.SIMPLE_PAGE_MASTER,
					Namespace.FO);
			DocumentUtil.setAttribute(simplePageMaster, FoAttributes.MASTER_NAME, page.getName());
			// TODO: add other regions
			DocumentUtil.appendElement(xsltDocument, simplePageMaster, FoTags.REGION_BODY, Namespace.FO);
		}

		for (PageFlow pageFlow : format.getPageFlows()) {
			Element simplePageMaster = DocumentUtil.appendElement(xsltDocument, foRoot, FoTags.PAGE_SEQUENCE,
					Namespace.FO);
			DocumentUtil.setAttribute(simplePageMaster, FoAttributes.MASTER_REFERENCE, pageFlow.getReferenceName());
			Element flow = DocumentUtil.appendElement(xsltDocument, simplePageMaster, FoTags.FLOW, Namespace.FO);
			DocumentUtil.setAttribute(flow, FoAttributes.FLOW_NAME, "xsl-region-body");
			for (org.ru.mse10.cvfpg.model.interfaces.Element flowElement : pageFlow.getChildren()) {
				handleElement(flowElement, flow, xsltDocument);
			}
		}
		DocumentUtil.serialize(xsltDocument, System.out);
		return null;
	}

	private static void handleElement(org.ru.mse10.cvfpg.model.interfaces.Element element, Element parent,
			Document document) {
		switch (element.getType()) {
		case BLOCK:
			appendBlockElement((Block) element, parent, document);
			break;
		case TEXT:
			appendTextElement((Text) element, parent, document);
			break;

		default:
			break;
		}
	}

	private static void appendBlockElement(Block block, Element parent, Document document) {
		Element blockElement = DocumentUtil.appendElement(document, parent, FoTags.BLOCK, Namespace.FO);
		for (org.ru.mse10.cvfpg.model.interfaces.Element child : block.getChildren()) {
			handleElement(child, blockElement, document);
		}
	}

	private static void appendTextElement(Text element, Element parent, Document document) {
		Element textElement = DocumentUtil.appendElement(document, parent, XsltTags.TEXT, Namespace.XSLT);
		textElement.setTextContent(element.getValue());
	}

	public static void main(String[] args) throws Exception {
		Page page = new Page();
		page.setName("A4");
		PageFlow flow = new PageFlow();
		flow.setReferenceName("A4");
		Block block = new Block();
		flow.getChildren().add(block);
		Text text = new Text();
		text.setValue("this is a test");
		block.getChildren().add(text);
		Format format = new Format();
		format.getPages().add(page);
		format.getPageFlows().add(flow);
		Generator.generate(format);
	}
}
